package com.dcy.znoa.service.software.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.dcy.znoa.common.exception.BusinessException;
import com.dcy.znoa.common.util.RedisClient;
import com.dcy.znoa.common.util.StringRandom;
import com.dcy.znoa.common.util.password.Md5PasswordEncoder;
import com.dcy.znoa.common.util.password.PasswordEncoder;
import com.dcy.znoa.common.util.pojo.JsonForList;
import com.dcy.znoa.controller.publiz.model.SelectBaseModel;
import com.dcy.znoa.controller.publiz.model.oper.AuditOperModel;
import com.dcy.znoa.controller.publiz.model.oper.BatchValidOperModel;
import com.dcy.znoa.controller.publiz.model.oper.SelectOperModel;
import com.dcy.znoa.controller.publiz.model.oper.UpdatePwdModel;
import com.dcy.znoa.dao.attendance.AttRuleDao;
import com.dcy.znoa.dao.user.OperDao;
import com.dcy.znoa.domain.Oper;
import com.dcy.znoa.domain.attendance.AttRule;
import com.dcy.znoa.service.publiz.DepartmentService;
import com.dcy.znoa.service.software.OperService;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.List;
@Slf4j
@Service
public class OperServiceImpl implements OperService {

    @Autowired
    OperDao userDao;
    @Autowired
    DepartmentService departmentService;
    @Autowired
    AttRuleDao attRuleDao;

    PasswordEncoder md5PasswordEncoder = new Md5PasswordEncoder();
    private static final String PASSWORD_SALT = "$znoa6666";

    @Override
    public Oper getById(Long id) {
        return userDao.selectById(id);
    }

    @Override
    public Oper getByMobile(String mobile) {
        Preconditions.checkNotNull(mobile);
        return userDao.selectOne(Oper.builder().phoneNo(mobile).build());
    }

    @Override
    public boolean verifyPassword(Long userId, String passwrod) {
        Preconditions.checkNotNull(userId);

        Oper user = userDao.selectById(userId);
        return md5PasswordEncoder.isPasswordValid(user.getPassword(), passwrod, PASSWORD_SALT);
    }

    @Override
    public List<Oper> selectUserList(Oper user) {
        return userDao.selectOperList(user);
    }

//    @Override
//    public List<Oper> queryList(SelectOperModel model) throws BusinessException, InvocationTargetException, IllegalAccessException{
//        Oper cp = new Oper();
//        BeanUtils.copyProperties(cp, model);
//        cp.setOperName(null);
//        cp.setPhoneNo(null);
//        EntityWrapper<Oper> ew = new EntityWrapper<>();
//        ew.setEntity(cp);
////        ew.eq("oper_id", model.getCompId())
////                .eq("oper_type", cp.getOperType())
////                .eq("comp_id", cp.getCompId())
////                .eq("dep_id", cp.getDepId())
////                .eq("duty_id", cp.getDutyId())
////                .eq("superior_id", cp.getSuperiorId())
////                .eq("sex", cp.getSex())
////                .eq("qr_code", cp.getQrCode())
////                .eq("employee_no", cp.getEmployeeNo())
////                .eq("phone_no", cp.getPhoneNo())
//        if(!Strings.isNullOrEmpty(model.getOperName())){
//            ew.like("oper_name", model.getOperName());
//        }
//        if(!Strings.isNullOrEmpty(model.getPhoneNo())){
//            ew.like("phone_no", model.getPhoneNo());
//        }
////        userDao.
//        List<Oper> list = userDao.selectListMapper(ew);
//         return null;
//    }

    @Override
    public JsonForList queryList(SelectOperModel model) throws BusinessException, InvocationTargetException, IllegalAccessException {
        EntityWrapper<Oper> ew = new EntityWrapper<>();
        Oper cp = new Oper();
        BeanUtils.copyProperties(cp, model);
        cp.setPhoneNo(null);
        cp.setOperName(null);
        ew.setEntity(cp);
        ew.like("oper_name", model.getOperName());
        ew.like("phone_no", model.getPhoneNo());
//        Integer total = SelectBaseModel.PageFill(model,ew,userDao);//加入分页参数
        Page page = new Page(model.getPageNum(), model.getPageSize());
        List<Oper> list = userDao.selectListMapper(model, page);
        return new JsonForList(list, page.getTotal());
    }

    @Override
    public Oper update(Oper cp) throws BusinessException {
        if (cp.getOperId() == null) {
            throw new BusinessException("404", "用户Id不能为空");
        }
        Oper operOld = userDao.selectById(cp.getOperId());
        if(operOld==null){
            throw new BusinessException("404", "用户ID不存在");
        }
        String phoneNoNew = cp.getPhoneNo();
        if(StringUtils.isNotBlank(phoneNoNew) && !phoneNoNew.equals(operOld.getPhoneNo())){//如果是修改手机号码
            //判断新的手机号码在不在库中
            List list = userDao.selectList(new EntityWrapper<Oper>().eq("phone_no", phoneNoNew));
            if (list != null && list.size() > 0) {
                throw new BusinessException("404", "用户手机号码" + phoneNoNew + "已经存在");
            }
        }
        String cpPassword = cp.getPassword();
        if (StringUtils.isNotBlank(cpPassword)) {
            String pwd = md5PasswordEncoder.encodePassword(cpPassword, PASSWORD_SALT);
            cp.setPassword(pwd);
        }
//        log.info(operOld.getDepId().toString());
//        log.info(cp.getDepId().toString());
        //如果用户新的部门id不为空，同时之前的部门ID为空 或  前后的部门ID都不为空且相互不等，则设置此用户的部门内员工编号
        if(cp.getDepId()!=null &&(operOld.getDepId()==null || operOld.getDepId().longValue()!=cp.getDepId().longValue())){
            cp.setDutyNo(getBiggestDutyNo(cp.getDepId()));
        }
        Integer result = userDao.updateById(cp);
        //有ID就用ID
        if (cp.getOperId() != null && result > 0) {
            Oper oper = userDao.selectById(cp.getOperId());
            departmentService.updateRedis(oper.getCompId());
            return cp;
        }
//        //没ID就用phoneNo
//        cp.setPassword(null);
//        Oper oper = userDao.selectOne(cp);
//        cp.setPassword(pwd);
//        if(userDao.updateById(cp)>0){
//            return oper;
//        }
        return null;
    }

    @Override
    public Integer batchValid(BatchValidOperModel model) {
        String operIds = model.getOperIds();
//        int ids = Splitter.on(",").;
//        Iterable split = Splitter.on(",").trimResults().omitEmptyStrings().split(operIds);
        String[] ids = operIds.split(",");
        int[] idInt = new int[ids.length];
        for (int i = 0; i < ids.length; i++) {
            idInt[i] = Integer.valueOf(ids[i]);
        }
        model.setIds(idInt);
        return userDao.batchValid(model);
    }

    @Override
    public Integer modifyPwd(Long operId, String pwd) throws BusinessException {
        if (operId == null || StringUtils.isBlank(pwd)) {
            throw new BusinessException("404", "缺乏入参！");
        }
        Oper oper = new Oper();
        oper.setOperId(operId);
        oper.setPassword(md5PasswordEncoder.encodePassword(pwd, PASSWORD_SALT));
//        oper.setPassword(pwd);
        return userDao.updateById(oper);
    }

    @Override
    public Oper updatePwd(UpdatePwdModel model) throws BusinessException, InvocationTargetException, IllegalAccessException {
        String rnd = RedisClient.get(RedisClient.DYSMS_PREFIX + model.getPhoneNo());
        if (!model.getRnd().equals(rnd)) {
            throw new BusinessException("404", "验证码错误或超时");
        }
        String pwd = md5PasswordEncoder.encodePassword(model.getPassword(), PASSWORD_SALT);
        Oper cp = new Oper();
        cp.setPhoneNo(model.getPhoneNo());
        Oper oper = userDao.selectOne(cp);
        oper.setPassword(pwd);
        if (userDao.updateById(oper) > 0) {
            return oper;
        }
        return null;
    }

    @Override
    public Integer top(Long operId) throws BusinessException {
        Oper oper = userDao.selectById(operId);
        Integer dutyNo;//原序号
        if (oper == null) {
            throw new BusinessException("804", "用户id:" + operId + " 不存在");
        }
        Long compId = oper.getCompId();
        if (compId == null) {
            throw new BusinessException("804", "用户没有归属的企业");
        }
        //查询小于原序号的用户，全部+1，大于的不动
        Oper cp = new Oper();
        EntityWrapper<Oper> ew = new EntityWrapper<>();
        ew.setEntity(cp);
        ew.eq("comp_id", compId);
        if (oper.getDepId() != null) {
            ew.eq("dep_id", oper.getDepId());
        }
        dutyNo = oper.getDutyNo();
        if (dutyNo != null) {
            ew.le("duty_no", dutyNo);
        }
        ew.isNotNull("duty_no");
        oper.setDutyNo(99999);
        userDao.updateById(oper);//有索引，不然要冲突，所以先update一次
        List<Oper> list = userDao.selectList(ew);
        int size = list.size();
        for (int i = size - 1; i >= 0; i--) {//从后往前
            list.get(i).setDutyNo(list.get(i).getDutyNo() + 1);
            userDao.updateById(list.get(i));
        }
        oper.setDutyNo(1);
        Integer result = userDao.updateById(oper);
        departmentService.updateRedis(oper.getCompId());
        return result;
    }

    @Override
    public Integer audit(AuditOperModel model) throws BusinessException, InvocationTargetException, IllegalAccessException {
        Long operId = model.getOperId();
        Integer isAudit = model.getIsAudit();
        if (operId == null || isAudit == null) {
            throw new BusinessException("404", "缺少参数");
        }
        Oper oper = userDao.selectById(operId);
        oper.setIsAudit(isAudit);
        switch (isAudit){//是否通过审核:默认0：未操作；1：通过；2：不通过
            case 0:
                throw new BusinessException("404", "审核设置为未操作不适合业务流程");
            case 1:
                if(model.getDepId()==null){
                    throw new BusinessException("404", "审核通过时部门为必选项");
                }
                //检验工号不能重复
                if(StringUtils.isNotBlank(model.getEmployeeNo())){
                    Oper operQuery = new Oper();
                    operQuery.setCompId(oper.getCompId());
                    operQuery.setEmployeeNo(model.getEmployeeNo());
                    Oper operResult = userDao.selectOne(operQuery);
                    if(operResult !=null){
                        throw new BusinessException("404", "员工工号已经存在");
                    }
                }
                BeanUtils.copyProperties(oper, model);
                oper.setValidFlag(1);
                break;
            case 2 :
                oper.setValidFlag(0);
                break;
            default:
                throw new BusinessException("404", "isAudit 只能为0、1、2这三种！");
        }
        if(StringUtils.isBlank(oper.getEmployeeNo())){
            oper.setEmployeeNo(StringRandom.getStringRandom(8));
        }
        userDao.updateById(oper);
        departmentService.updateRedis(oper.getCompId());
        return 1;
    }

    @Override
    public Oper save(Oper user) throws BusinessException {
        List list = userDao.selectList(new EntityWrapper<Oper>().eq("phone_no", user.getPhoneNo()));
        if (list != null && list.size() > 0) {
            throw new BusinessException("404", "用户手机号码" + user.getPhoneNo() + "已经存在");
        }
        if (!Strings.isNullOrEmpty(user.getPassword())) {
            user.setPassword(md5PasswordEncoder.encodePassword(user.getPassword(), PASSWORD_SALT));
        }
//        user.setIsAudit(0);//是否通过审核:默认0：未操作；1：通过；2：不通过

        //查询，如果有默认的考勤规则，就把用户做关联
        AttRule attRule = new AttRule();
        EntityWrapper<AttRule> ew = new EntityWrapper();
        ew.setEntity(attRule);
        ew.eq("comp_id",user.getCompId()).eq("is_default",1);
        List<AttRule> attRuleList = attRuleDao.selectList(ew);
        if(!attRuleList.isEmpty()){
            user.setAttRuleNo(attRuleList.get(0).getAttRuleNo());
        }
        userDao.insertAllColumn(user);
        departmentService.updateRedis(user.getCompId());
        return user;
    }
    //根据部门ID，查看部门下可以设置的最大部门内员工编号
    @Override
    public Integer getBiggestDutyNo(Long depId) throws BusinessException {
        if(depId == null){
            throw new BusinessException("404", "depId不能为空");
        }
        List<Oper> list = userDao.selectList(new EntityWrapper<Oper>().eq("dep_id",depId).orderBy("duty_no",false).last("limit 1"));
        if(list.isEmpty()||list.get(0).getDutyNo()==null){
           return 1;
        }
        int result =  list.get(0).getDutyNo().intValue()+1;
        log.info("result = " + result);
        return result;
    }

}
